// EMERGENT GAME TECHNOLOGIES PROPRIETARY INFORMATION
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Emergent Game Technologies and may not 
// be copied or disclosed except in accordance with the terms of that 
// agreement.
//
//      Copyright (c) 1996-2008 Emergent Game Technologies.
//      All Rights Reserved.
//
// Emergent Game Technologies, Chapel Hill, North Carolina 27517
// http://www.emergent.net
//---------------------------------------------------------------------------

#ifndef GNTABSTRACTPOOLALLOCATOR_H
#define GNTABSTRACTPOOLALLOCATOR_H

#define GnAllocatorShutdown(T) GnTAbstractPoolAllocator<T>::_SDMShutdown();

#ifdef GNDEBUG
#define GnAllocatorDeclareStatics(T, BLOCKSIZE) \
	template <> GnTAbstractPoolAllocator<T>::AllocNode* \
	GnTAbstractPoolAllocator<T>::ms_pkBlockHeader = NULL; \
	template <> GnTAbstractPoolAllocator<T>::AllocNode* \
	GnTAbstractPoolAllocator<T>::ms_pkFreeMem = NULL; \
	template <> GnCriticalSection \
	GnTAbstractPoolAllocator<T>::ms_kCriticalSection; \
	template <> unsigned int \
	GnTAbstractPoolAllocator<T>::ms_uiBlockSize = BLOCKSIZE; \
	template <> unsigned int \
	GnTAbstractPoolAllocator<T>::ms_uiAllocated = 0; \
	template <> unsigned int \
	GnTAbstractPoolAllocator<T>::ms_uiMaxAllocated = 0;
#else //GNDEBUG
#define GnAllocatorDeclareStatics(T, BLOCKSIZE) \
	template <> GnTAbstractPoolAllocator<T>::AllocNode* \
	GnTAbstractPoolAllocator<T>::ms_pkBlockHeader = NULL; \
	template <> GnTAbstractPoolAllocator<T>::AllocNode* \
	GnTAbstractPoolAllocator<T>::ms_pkFreeMem = NULL; \
	template <> unsigned int \
	GnTAbstractPoolAllocator<T>::ms_uiBlockSize = BLOCKSIZE; \
	template <> GnCriticalSection \
	GnTAbstractPoolAllocator<T>::ms_kCriticalSection;
#endif //GNDEBUG

#define GnAllocatorSetBlockSize(T, BLOCKSIZE) \
	GnTAbstractPoolAllocator<T>::SetBlockSize(BLOCKSIZE);
#define GnAllocatorEnsureFreeMem(T) \
	GnTAbstractPoolAllocator<T>::EnsureFreeMem();

template <class T> class GnTAbstractPoolAllocator
{
public:

	// Virtuals are not used because they add additional memory for each
	// class derived. This class can be thought of as abstract with the
	// following commented classes as pure virtuals.
	// virtual void* Allocate() = 0;
	// virtual void Deallocate (void* p) = 0;

	static void _SDMShutdown();
	static void SetBlockSize(unsigned int uiBlockSize);
	static void EnsureFreeMem();
	static void CreateFreeMem();

protected:
	// list is doubly-linked
	class AllocNode : public GnMemoryObject
	{
	public:
		AllocNode* m_pkNext;
		void* m_pkData;
		T m_element;
	};

	static AllocNode* ms_pkBlockHeader;
	static AllocNode* ms_pkFreeMem;
	static unsigned int ms_uiBlockSize;

	static GnCriticalSection ms_kCriticalSection;

#ifdef GNDEBUG
	static unsigned int ms_uiAllocated;
	static unsigned int ms_uiMaxAllocated;
#endif
};

//---------------------------------------------------------------------------
// Inline include
#include "GnTAbstractPoolAllocator.inl"
///---------------------------------------------------------------------------

#endif // GNTABSTRACTPOOLALLOCATOR_H

